#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import json
import os
import shutil
import time
import psutil


from common.parse_parafile import ParamFileUtil
from exchange import log
from exchange.backup.exchange_backup import get_command_result
from exchange.commons.common import init_hub_path
from exchange.commons.const import ExchangeJobInfo, ExchangeWindowsPath, ParamConstant, VSSToolOperation, \
    ExecCmdResult, JobBackupType
from exchange.commons.exchange_function_tool import log_start_end, out_result_with_job_info, \
    progress_notify_with_job_info
from exchange.commons.exchange_param_parse import ExchangeParamParse
from common.common import get_host_sn


# Exchange备份后置任务基类
def wait_for_process_to_end(process_id):
    try:
        process = psutil.Process(process_id)
        # 如果进程已经终止，这里检查它的状态并捕获异常
        if not process.is_running():
            log.info(f"Process {process_id} has already ended.")
            return
        while process.is_running():
            time.sleep(3)
        log.info(f"Process {process_id} has ended.")
    except psutil.NoSuchProcess:
        log.info(f"No process with PID {process_id} was found.")


class ExchangeBackupPost:
    def __init__(self, pid):
        self._pid = pid
        self._param = ParamFileUtil.parse_param_file(pid)

    @log_start_end()
    @out_result_with_job_info()
    @progress_notify_with_job_info()
    def do_post_task(self, job_info: ExchangeJobInfo):
        # 删除临时文件
        # 删除copy_info临时文件
        cache_path = ExchangeParamParse.get_cache_path(self._param).replace("/", "\\")
        log.info(f"Get cache path {cache_path}")
        copy_info_dir = os.path.join(cache_path, "copyInfo").replace("/", "\\")
        if os.path.exists(copy_info_dir):
            shutil.rmtree(copy_info_dir)
            log.info(f"Delete copy info dir {copy_info_dir}")
        else:
            log.info(f"Not delete copy info dir {copy_info_dir}")

        # 解析snapInfo.json
        data_hub = ExchangeParamParse.get_data_path(self._param)
        backup_type = self._param.get("job").get("jobParam").get("backupType")
        # 针对全量备份和日志备份不同场景获取meta_hub方式不同
        if backup_type == JobBackupType.EXCHANGE_BACKUP_LOG:
            meta_hub = ExchangeParamParse.get_log_path(self._param)
            agent_id = get_host_sn().split("-")[0]
            meta_hub = meta_hub.replace("/", "\\") + f"\\{agent_id}"
        else:
            meta_hub = ExchangeParamParse.get_meta_path(self._param)
            data_hub, meta_hub = init_hub_path(data_hub, meta_hub)

        snap_info_path = ExchangeWindowsPath.UNC + meta_hub + f"\\{job_info.job_id}.json"
        if not os.path.exists(snap_info_path):
            return True
        with open(snap_info_path, 'r') as f_read:
            snap_infos = json.load(f_read)
        for snap_info_data in snap_infos['snapInfo']:
            volume_id = snap_info_data['volumeId']
            if volume_id is None or len(volume_id) == 0:
                return False
            # 删除快照
            vss_exec_param = "{} {} {}".format(ParamConstant.VSS_TOOL_PATH, VSSToolOperation.DELETE,
                                               volume_id)
            code, out, err = get_command_result(vss_exec_param)
            # 移除功能
            if os.path.exists(ParamConstant.VIRTUAL_PATH + f"{volume_id}"):
                shutil.rmtree(ParamConstant.VIRTUAL_PATH + f"{volume_id}")
            if code != ExecCmdResult.SUCCESS:
                log.error(f"vss result :{out} ,err :{err}")
                return False
        # 后置任务直接返回成功
        return True

    def get_job_info(self):
        job_info = ExchangeJobInfo(pid=self._pid,
                                   job_id=ExchangeParamParse.get_job_id(self._param),
                                   sub_job_id=ExchangeParamParse.get_sub_job_id(self._param),
                                   copy_id=ExchangeParamParse.get_copy_id(self._param),
                                   backup_type=ExchangeParamParse.get_type(self._param),
                                   meta_path=ExchangeParamParse.get_meta_path(self._param),
                                   data_reps=ExchangeParamParse.get_data_reps(self._param),
                                   cache_path=ExchangeParamParse.get_cache_path(self._param),
                                   backup_result=ExchangeParamParse.get_backup_result(self._param))
        return job_info
